using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace XSResearch.Monitoring
{
    public class PerformanceMetrics
    {
        public long MemoryUsageMB { get; set; }
        public double CpuUsagePercent { get; set; }
        public TimeSpan ExecutionTime { get; set; }
    }

    public class PerformanceMonitor : IDisposable
    {
        private readonly Stopwatch _stopwatch;
        private readonly PerformanceCounter _cpuCounter;
        private readonly AppLogger _logger;
        private readonly Dictionary<string, PerformanceMetrics> _operations;

        public PerformanceMonitor(AppLogger logger)
        {
            _logger = logger;
            _stopwatch = Stopwatch.StartNew();
            _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
            _operations = new Dictionary<string, PerformanceMetrics>();
#if !WINDOWS
            _lastCpuTime = Process.GetCurrentProcess().TotalProcessorTime;
            _lastCpuCheck = DateTime.Now;
#endif
        }

        public void StartOperation(string operationName)
        {
            var metrics = new PerformanceMetrics
            {
                MemoryUsageMB = Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024
            };
            _operations[operationName] = metrics;
            _stopwatch.Restart();
        }

        public void EndOperation(string operationName)
        {
            _stopwatch.Stop();
            if (_operations.TryGetValue(operationName, out var metrics))
            {
                metrics.ExecutionTime = _stopwatch.Elapsed;
                
#if WINDOWS
                metrics.CpuUsagePercent = _cpuCounter.NextValue();
#else
                var process = Process.GetCurrentProcess();
                var newCpuTime = process.TotalProcessorTime;
                var newCheckTime = DateTime.Now;
                
                var cpuUsedMs = (newCpuTime - _lastCpuTime).TotalMilliseconds;
                var totalMs = (newCheckTime - _lastCpuCheck).TotalMilliseconds;
                var cpuUsage = (cpuUsedMs / (Environment.ProcessorCount * totalMs)) * 100;
                
                metrics.CpuUsagePercent = Math.Round(cpuUsage, 2);
                _lastCpuTime = newCpuTime;
                _lastCpuCheck = newCheckTime;
#endif
                
                LogMetrics(operationName, metrics);
            }
        }

        private void LogMetrics(string operationName, PerformanceMetrics metrics)
        {
            _logger.Log("[Perf] " + operationName + " - " +
                       "Time: " + metrics.ExecutionTime.TotalMilliseconds + "ms | " +
                       "CPU: " + metrics.CpuUsagePercent.ToString("0.00") + "% | " +
                       "Memory: " + metrics.MemoryUsageMB + "MB", 
                       LogLevel.Debug);
        }

        public void Dispose()
        {
#if WINDOWS
            _cpuCounter?.Dispose();
#endif
        }
    }
}